using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Matrix.ServiceDiscovery.Dtos;
using Matrix.ServiceDiscovery.Entities;
using Matrix.ServiceDiscovery.Enums;
using Matrix.ServiceDiscovery.Permissions;

namespace Matrix.ServiceDiscovery.Services
{
    /// <summary>
    /// 服务发现应用服务协调器
    /// 基于CQRS模式协调查询和命令服务
    /// </summary>
    [Authorize(ServiceDiscoveryPermissions.Services.Default)]
    public class ServiceDiscoveryAppService : ApplicationServiceBase, IServiceDiscoveryAppService
    {
        private readonly ServiceDiscoveryQueryService _queryService;
        private readonly ServiceDiscoveryCommandService _commandService;
        private readonly ServiceDiscoveryCacheService _cacheService;
        private readonly ILogger<ServiceDiscoveryAppService> _logger;

        public ServiceDiscoveryAppService(
            ServiceDiscoveryQueryService queryService,
            ServiceDiscoveryCommandService commandService,
            ServiceDiscoveryCacheService cacheService,
            ILogger<ServiceDiscoveryAppService> logger)
        {
            _queryService = queryService;
            _commandService = commandService;
            _cacheService = cacheService;
            _logger = logger;
        }

        #region 查询操作 - 委托给查询服务

        public async Task<ServiceInfoDto> GetAsync(Guid id)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.GetAsync(id);
        }

        public async Task<ServiceInfoDto> GetByNameAsync(string serviceName)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.GetByNameAsync(serviceName);
        }

        public async Task<PagedResultDto<ServiceInfoDto>> GetListAsync(GetServiceListInput input)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.GetListAsync(input);
        }

        public async Task<ListResultDto<ServiceInstanceDto>> GetInstancesAsync(Guid serviceId)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.GetInstancesAsync(serviceId);
        }

        public async Task<ListResultDto<ServiceInstanceDto>> GetHealthyInstancesAsync(string serviceName)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.GetHealthyInstancesAsync(serviceName);
        }

        public async Task<LoadBalancingConfigDto> GetLoadBalancingConfigAsync(Guid serviceId)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.GetLoadBalancingConfigAsync(serviceId);
        }

        public async Task<PagedResultDto<HealthCheckRecordDto>> GetHealthCheckRecordsAsync(
            Guid serviceInstanceId,
            GetHealthCheckRecordsInput input)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.GetHealthCheckRecordsAsync(serviceInstanceId, input);
        }

        public async Task<PagedResultDto<ServiceInfoDto>> SearchServicesAsync(SearchServicesInput input)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.SearchServicesAsync(input);
        }

        public async Task<ServiceStatisticsDto> GetServiceStatisticsAsync()
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);
            return await _queryService.GetServiceStatisticsAsync();
        }

        #endregion

        #region 命令操作 - 委托给命令服务

        [Authorize(ServiceDiscoveryPermissions.Services.Create)]
        public async Task<ServiceInfoDto> CreateAsync(CreateServiceInfoDto input)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Create);

            var result = await _commandService.CreateAsync(input);

            // 清理相关缓存
            await _cacheService.InvalidateServiceCachesAsync(result.Id, result.Name);

            return result;
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Update)]
        public async Task<ServiceInfoDto> UpdateAsync(Guid id, UpdateServiceInfoDto input)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Update);

            var result = await _commandService.UpdateAsync(id, input);

            // 清理相关缓存
            await _cacheService.InvalidateServiceCachesAsync(result.Id, result.Name);

            return result;
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Delete)]
        public async Task DeleteAsync(Guid id)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Delete);

            // 先获取服务信息用于清理缓存
            var service = await _queryService.GetAsync(id);

            await _commandService.DeleteAsync(id);

            // 清理相关缓存
            await _cacheService.InvalidateServiceCachesAsync(id, service.Name);
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Manage)]
        public async Task<ServiceInfoDto> ActivateAsync(Guid id)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Manage);

            var result = await _commandService.ActivateAsync(id);

            // 清理相关缓存
            await _cacheService.InvalidateServiceCachesAsync(result.Id, result.Name);

            return result;
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Manage)]
        public async Task<ServiceInfoDto> DeactivateAsync(Guid id)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Manage);

            var result = await _commandService.DeactivateAsync(id);

            // 清理相关缓存
            await _cacheService.InvalidateServiceCachesAsync(result.Id, result.Name);

            return result;
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Manage)]
        public async Task<ServiceInstanceDto> RegisterInstanceAsync(RegisterServiceInstanceDto input)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Manage);

            var result = await _commandService.RegisterInstanceAsync(input);

            // 清理相关缓存
            await _cacheService.InvalidateInstanceCachesAsync(
                result.ServiceId,
                result.ServiceName,
                result.Id);

            return result;
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Manage)]
        public async Task UnregisterInstanceAsync(Guid serviceId, string instanceId)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Manage);

            // 先获取实例信息用于清理缓存
            var instances = await _queryService.GetInstancesAsync(serviceId);
            var instance = instances.Items.FirstOrDefault(x => x.InstanceId == instanceId);

            await _commandService.UnregisterInstanceAsync(serviceId, instanceId);

            // 清理相关缓存
            if (instance != null)
            {
                await _cacheService.InvalidateInstanceCachesAsync(
                    serviceId,
                    instance.ServiceName,
                    instance.Id);
            }
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Manage)]
        public async Task UpdateInstanceHealthStatusAsync(Guid instanceId, HealthStatus status)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Manage);

            // 先获取实例信息用于清理缓存
            var instance = await GetInstanceByIdAsync(instanceId);

            await _commandService.UpdateInstanceHealthStatusAsync(instanceId, status);

            // 清理相关缓存
            if (instance != null)
            {
                await _cacheService.InvalidateInstanceCachesAsync(
                    instance.ServiceId,
                    instance.ServiceName,
                    instanceId);
            }
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Manage)]
        public async Task RecordInstanceHeartbeatAsync(Guid instanceId)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Manage);

            await _commandService.RecordInstanceHeartbeatAsync(instanceId);

            // 心跳记录不需要立即清理缓存，让缓存自然过期
        }

        [Authorize(ServiceDiscoveryPermissions.Services.Manage)]
        public async Task<LoadBalancingConfigDto> UpdateLoadBalancingConfigAsync(
            Guid serviceId,
            UpdateLoadBalancingConfigDto input)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Manage);

            var result = await _commandService.UpdateLoadBalancingConfigAsync(serviceId, input);

            // 清理相关缓存
            var service = await _queryService.GetAsync(serviceId);
            await _cacheService.InvalidateServiceCachesAsync(serviceId, service.Name);

            return result;
        }

        #endregion

        #region 扩展方法

        /// <summary>
        /// 批量获取服务信息
        /// </summary>
        [Authorize(ServiceDiscoveryPermissions.Services.Default)]
        public async Task<Dictionary<string, ServiceInfoDto>> GetBatchAsync(List<string> serviceNames)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Default);

            var tasks = serviceNames.Select(name => GetByNameAsync(name));
            var results = await Task.WhenAll(tasks);

            return serviceNames.Zip(results, (name, result) => new { Key = name, Value = result })
                .ToDictionary(x => x.Key, x => x.Value);
        }

        /// <summary>
        /// 健康检查批量更新
        /// </summary>
        [Authorize(ServiceDiscoveryPermissions.Services.Manage)]
        public async Task BatchUpdateHealthStatusAsync(List<UpdateHealthStatusInput> inputs)
        {
            await CheckPolicyAsync(ServiceDiscoveryPermissions.Services.Manage);

            var tasks = inputs.Select(async input =>
            {
                await UpdateInstanceHealthStatusAsync(input.InstanceId, input.Status);
            });

            await Task.WhenAll(tasks);
        }

        #endregion

        #region Private Helper Methods

        private async Task<ServiceInstanceDto?> GetInstanceByIdAsync(Guid instanceId)
        {
            // 通过查询所有实例来查找指定实例
            // 在实际项目中，可能需要在查询服务中添加专门的方法
            try
            {
                var allServices = await _queryService.GetListAsync(new GetServiceListInput { MaxResultCount = 1000 });
                foreach (var service in allServices.Items)
                {
                    var instances = await _queryService.GetInstancesAsync(service.Id);
                    var instance = instances.Items.FirstOrDefault(x => x.Id == instanceId);
                    if (instance != null)
                        return instance;
                }
            }
            catch
            {
                // 忽略错误，返回null
            }

            return null;
        }

        #endregion
    }
}